'use strict';
import React, {
    Component
} from 'react';
import PropTypes from 'prop-types';

import ReactNative, {
    EdgeInsetsPropType,
    Image,
    NativeMethodsMixin,
    Platform,
    requireNativeComponent,
    StyleSheet,
    View,
    UIManager,
    processColor,
    ColorPropType,
    ViewPropTypes,
} from 'react-native';

import MapTypes from './MapTypes';
import UserTrackingMode from './UserTrackingMode';
import baiduMapState from './BaiduMapState';

import deprecatedPropType from 'react-native/Libraries/Utilities/deprecatedPropType';
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';


/*
const RCTBaiduMapConstants = UIManager.RCTBaiduMap.Constants;

type Event = Object;
export type MAAnnotationDragState = $Enum<{
  idle: string;
  starting: string;
  dragging: string;
  canceling: string;
  ending: string;
}>;
*/

let userLocationDefaultOptions = {
    distanceFilter: 5
};

export default class YuanXinMapView extends Component {

    static propTypes = {
        ...ViewPropTypes,
        /**
         * Used to style and layout the `MapView`.  See `StyleSheet.js` and
         * `ViewStylePropTypes.js` for more info.
         */
        style: ViewPropTypes.style,

        /**
         * 是否显示当前用户定位
         */
        showsUserLocation: PropTypes.bool,
        /**
         * 是否显示比例尺
         */
        showMapScaleBar: PropTypes.bool,

        userLocationViewParams: PropTypes.shape({
            /**
             * 定位图标XY轴偏移量(屏幕坐标)
             */
            offsetX: PropTypes.number,
            offsetY: PropTypes.number,
            /**
             * 精度圈是否显示
             */
            showAccuracyCircle: PropTypes.bool,
            /**
             * 精度圈 填充颜色
             */
            accuracyCircleFillColor: ColorPropType,
            /**
             * 精度圈 边框颜色
             */
            accuracyCircleStrokeColor: ColorPropType,
            /**
             * 跟随态旋转角度是否生效
             */
            rotateAngleValid: PropTypes.bool,
            /**
             * 定位图标名称，需要将该图片放到 mapapi.bundle/images 目录下
             */
            image: Image.propTypes.source

        }),

        autoZoomToSpan: PropTypes.bool,

        /**
         * 用户定位显示方式
         */
        userTrackingMode: PropTypes.number,

        /**
         * 当前地图的中心点，改变该值时，地图的比例尺级别不会发生变化
         */
        mapCenter: PropTypes.shape({
            /**
             * Coordinates for the center of the map.
             */
            latitude: PropTypes.number.isRequired,
            longitude: PropTypes.number.isRequired,
        }),

        /**
         * If `false` points of interest won't be displayed on the map.
         * Default value is `true`.
         * @platform ios
         */
        showsPointsOfInterest: PropTypes.bool,

        /**
         * If `false` compass won't be displayed on the map.
         * Default value is `true`.
         * @platform ios
         */
        showsCompass: PropTypes.bool,

        /**
         * 设定地图View能否支持用户多点缩放(双指)
         */
        zoomEnabled: PropTypes.bool,

        /**
         * When this property is set to `true` and a valid camera is associated with
         * the map, the camera’s heading angle is used to rotate the plane of the
         * map around its center point. When this property is set to `false`, the
         * camera’s heading angle is ignored and the map is always oriented so
         * that true north is situated at the top of the map view
         */
        rotateEnabled: PropTypes.bool,

        /**
         * When this property is set to `true` and a valid camera is associated
         * with the map, the camera’s pitch angle is used to tilt the plane
         * of the map. When this property is set to `false`, the camera’s pitch
         * angle is ignored and the map is always displayed as if the user
         * is looking straight down onto it.
         */
        pitchEnabled: PropTypes.bool,

        /**
         * If `false` the user won't be able to change the map region being displayed.
         * Default value is `true`.
         */
        scrollEnabled: PropTypes.bool,

        /**
         * The map type to be displayed.
         *
         * - standard: standard road map (default)
         * - satellite: satellite view
         * - hybrid: satellite view with roads and points of interest overlaid
         *
         * @platform ios
         */
        mapType: PropTypes.number,

        /**
         * The region to be displayed by the map.
         *
         * The region is defined by the center coordinates and the span of
         * coordinates to display.
         */
        region: PropTypes.shape({
            /**
             * Coordinates for the center of the map.
             */
            latitude: PropTypes.number.isRequired,
            longitude: PropTypes.number.isRequired,

            /**
             * Distance between the minimum and the maximum latitude/longitude
             * to be displayed.
             */
            latitudeDelta: PropTypes.number,
            longitudeDelta: PropTypes.number,
        }),

        /**
         * Map annotations with title/subtitle.
         * @platform ios
         */
        annotations: PropTypes.arrayOf(PropTypes.shape({
            /**
             * The location of the annotation.
             */
            latitude: PropTypes.number.isRequired,
            longitude: PropTypes.number.isRequired,

            /**
             * Whether the pin drop should be animated or not
             */
            animateDrop: PropTypes.bool,

            /**
             * Whether the pin should be draggable or not
             */
            draggable: PropTypes.bool,

            /**
             * Event that fires when the annotation drag state changes.
             */
            onDragStateChange: PropTypes.func,

            /**
             * Event that fires when the annotation gets was tapped by the user
             * and the callout view was displayed.
             */
            onFocus: PropTypes.func,

            /**
             * Event that fires when another annotation or the mapview itself
             * was tapped and a previously shown annotation will be closed.
             */
            onBlur: PropTypes.func,

            /**
             * Annotation title/subtile.
             */
            title: PropTypes.string,
            subtitle: PropTypes.string,

            /**
             * Callout views.
             */
            leftCalloutView: PropTypes.element,
            rightCalloutView: PropTypes.element,

            /**
             * The pin color. This can be any valid color string, or you can use one
             * of the predefined PinColors constants. Applies to both standard pins
             * and custom pin images.
             *
             * Note that on iOS 8 and earlier, only the standard PinColor constants
             * are supported for regular pins. For custom pin images, any tintColor
             * value is supported on all iOS versions.
             */
            tintColor: PropTypes.number,

            /**
             * Custom pin image. This must be a static image resource inside the app.
             */
            image: Image.propTypes.source,

            /**
             * Custom pin view. If set, this replaces the pin or custom pin image.
             */
            view: PropTypes.element,

            /**
             * annotation id
             */
            id: PropTypes.string,

            /**
             * Deprecated. Use the left/right/detailsCalloutView props instead.
             */
            hasLeftCallout: PropTypes.bool,
            hasRightCallout: PropTypes.bool,
            onLeftCalloutPress: PropTypes.func,
            onRightCalloutPress: PropTypes.func,
        })),

        /**
         * Map overlays
         * @platform ios
         */
        overlays: PropTypes.arrayOf(PropTypes.shape({
            /**
             * Polyline coordinates
             */
            coordinates: PropTypes.arrayOf(PropTypes.shape({
                latitude: PropTypes.number.isRequired,
                longitude: PropTypes.number.isRequired
            })),

            /**
             * Line attributes
             */
            lineWidth: PropTypes.number,
            strokeColor: ColorPropType,
            fillColor: ColorPropType,

            /**
             * Overlay id
             */
            id: PropTypes.string
        })),

        /**
         * Maximum size of area that can be displayed.
         * @platform ios
         */
        maxDelta: PropTypes.number,

        /**
         * Minimum size of area that can be displayed.
         * @platform ios
         */
        minDelta: PropTypes.number,

        /**
         * 地图缩放比例
         */
        zoomLevel: PropTypes.number,
        /**
         * 是否禁用所有的手势
         */
        gesturesEnabled: PropTypes.bool,

        /**
         * 设定地图View能否支持用户缩放(双击或双指单击)
         */
        zoomEnabledWithTap: PropTypes.bool,
        /**
         * 设定地图是否打开路况图层
         */
        trafficEnabled: PropTypes.bool,
        /**
        * 设定地图是否打开百度城市热力图图层（百度自有数据）,注：地图层级大于11时，可显示热力图
        */
        baiduHeatMapEnabled: PropTypes.bool,
        /**
         * 设定地图是否现显示3D楼块效果
         */
        buildingsEnabled: PropTypes.bool,
        /**
         * Insets for the map's legal label, originally at bottom left of the map.
         * See `EdgeInsetsPropType.js` for more information.
         * @platform ios
         */
        legalLabelInsets: EdgeInsetsPropType,

        /**
         * Callback that is called continuously when the user is dragging the map.
         */
        onRegionChange: PropTypes.func,

        /**
         * Callback that is called once, when the user is done moving the map.
         */
        onRegionChangeComplete: PropTypes.func,

        /**
         * Deprecated. Use annotation onFocus and onBlur instead.
         */
        onAnnotationPress: PropTypes.func,
        /**
         * 开启定位后，用户位置发生变化时触发
         */
        onDidChangeUserLocation: PropTypes.func,
        /**
         * @platform android
         */
        active: PropTypes.bool,
    };

    static defaultProps = {
        zoomLevel: 15,
        showsUserLocation: false, //是否开启当前用户定位
        trafficEnabled: false,
        baiduHeatMapEnabled: false,
        gesturesEnabled: false, //是否禁用所有手势
        zoomEnabledWithTap: true, //设定地图View能否支持用户缩放(双击或双指单击)
        buildingsEnabled: false,
        mapType: MapTypes.NORMAL,
        userTrackingMode: UserTrackingMode.ModeNone  //用户定位显示方式
    };

    constructor(props) {
        super(props);
        // this.onDidChangeUserLocation = this._onDidChangeUserLocation.bind(this)
        this.state = {
          annotations: props.annotations
        }
    }

    render() {
        const children = [];
        // const {annotations, overlays, userLocationViewParams} = this.props;
        const {overlays, userLocationViewParams} = this.props;
        const {annotations} = this.state;
        let {followUserLocation, showsZoomControl} = this.props;
        const annotationsReal = annotations && annotations.map((annotation: Object) => {
            let {
                id,
                image,
                tintColor,
                view,
                leftCalloutView,
                rightCalloutView,
            } = annotation;

            if (!view && image && tintColor) {
                view = <Image
                    style={{
                        tintColor: processColor(tintColor),
                    }}
                    source={image}
                />;
                image = undefined;
            }
            if (view) {
                if (image) {
                    console.warn('`image` and `view` both set on annotation. Image will be ignored.');
                }
                var viewIndex = children.length;
                children.push(React.cloneElement(view, {
                    key: children.length,
                    style: [styles.annotationView, view.props.style || {}, {left: -999}]
                }));
            }
            if (leftCalloutView) {
                var leftCalloutViewIndex = children.length;
                children.push(React.cloneElement(leftCalloutView, {
                    key: children.length,
                    style: [styles.calloutView, leftCalloutView.props.style || {}, {left: -999}]
                }));
            }
            if (rightCalloutView) {
                var rightCalloutViewIndex = children.length;
                children.push(React.cloneElement(rightCalloutView, {
                    key: children.length,
                    style: [styles.calloutView, rightCalloutView.props.style || {}, {left: -999}]
                }));
            }

            let result = Object.assign({}, annotation, {
                tintColor: tintColor && processColor(tintColor),
                image,
                viewIndex,
                leftCalloutViewIndex,
                rightCalloutViewIndex,
                view: undefined,
                leftCalloutView: undefined,
                rightCalloutView: undefined,
            });
            result.id = id || encodeURIComponent(JSON.stringify(result));
            result.image = image && resolveAssetSource(image);
            return result;
        });
        const overlaysReal = overlays && overlays.map((overlay: Object) => {
            let {id, fillColor, strokeColor} = overlay;
            let result = Object.assign(overlay, {
                strokeColor: strokeColor && processColor(strokeColor),
                fillColor: fillColor && processColor(fillColor),
            });
            result.id = id || encodeURIComponent(JSON.stringify(result));
            return result;
        });

        const findByAnnotationId = (annotationId: string) => {
            if (!annotationsReal) {
                return null;
            }
            for (let i = 0, l = annotationsReal.length; i < l; i++) {
                if (annotationsReal[i].id === annotationId) {
                    return annotationsReal[i];
                }
            }
            return null;
        };

        // TODO: these should be separate events, to reduce bridge traffic
        let onPress, onAnnotationDragStateChange, onAnnotationFocus, onAnnotationBlur;
        if (annotationsReal) {
            onPress = (event: Event) => {
                if (event.nativeEvent.action === 'annotation-click') {
                    // TODO: Remove deprecated onAnnotationPress API call later.
                    this.props.onAnnotationPress &&
                    this.props.onAnnotationPress(event.nativeEvent.annotation);
                } else if (event.nativeEvent.action === 'callout-click') {
                    const annotation = findByAnnotationId(event.nativeEvent.annotationId);
                    if (annotation) {
                        // Pass the right function
                        if (event.nativeEvent.side === 'left' && annotation.onLeftCalloutPress) {
                            annotation.onLeftCalloutPress(event.nativeEvent);
                        } else if (event.nativeEvent.side === 'right' && annotation.onRightCalloutPress) {
                            annotation.onRightCalloutPress(event.nativeEvent);
                        }
                    }
                }
            };
            onAnnotationDragStateChange = (event: Event) => {
                const annotation = findByAnnotationId(event.nativeEvent.annotationId);
                if (annotation) {
                    // Update location
                    annotation.latitude = event.nativeEvent.latitude;
                    annotation.longitude = event.nativeEvent.longitude;
                    // Call callback
                    annotation.onDragStateChange &&
                    annotation.onDragStateChange(event.nativeEvent);
                }
            };
            onAnnotationFocus = (event: Event) => {
                const annotation = findByAnnotationId(event.nativeEvent.annotationId);
                if (annotation && annotation.onFocus) {
                    annotation.onFocus(event.nativeEvent);
                }
            };
            onAnnotationBlur = (event: Event) => {
                const annotation = findByAnnotationId(event.nativeEvent.annotationId);
                if (annotation && annotation.onBlur) {
                    annotation.onBlur(event.nativeEvent);
                }
            };
        }

        // TODO: these should be separate events, to reduce bridge traffic
        if (this.props.onRegionChange || this.props.onRegionChangeComplete) {
            var onChange = (event: Event) => {
                if (event.nativeEvent.continuous) {
                    this.props.onRegionChange &&
                    this.props.onRegionChange(event.nativeEvent.region);
                } else {
                    this.props.onRegionChangeComplete &&
                    this.props.onRegionChangeComplete(event.nativeEvent.region);
                }
            };
        }

        // followUserLocation defaults to true if showUserLocation is set
        if (followUserLocation === undefined) {
            followUserLocation = this.props.showUserLocation;
        }

        if (!!userLocationViewParams) {
            let {accuracyCircleFillColor, accuracyCircleStrokeColor, image} = userLocationViewParams;
            accuracyCircleFillColor = accuracyCircleFillColor && processColor(accuracyCircleFillColor);
            accuracyCircleStrokeColor = accuracyCircleStrokeColor && processColor(accuracyCircleStrokeColor);
            userLocationViewParams.accuracyCircleFillColor = accuracyCircleFillColor;
            userLocationViewParams.accuracyCircleStrokeColor = accuracyCircleStrokeColor;

            image = image && resolveAssetSource(image);
            userLocationViewParams.image = image;
        }

        if (showsZoomControl === undefined) {
            showsZoomControl = false;
        }

        return (
            <RCTBaiduMap
                {...this.props}
                ref="baiduMap"
                annotations={annotationsReal}
                children={children}
                followUserLocation={followUserLocation}
                showsZoomControl={showsZoomControl}
                overlays={overlaysReal}
                onPress={onPress}
                onChange={onChange}
                onAnnotationDragStateChange={onAnnotationDragStateChange}
                onAnnotationFocus={onAnnotationFocus}
                onAnnotationBlur={onAnnotationBlur}
                userLocationViewParams={userLocationViewParams}
                onDidChangeUserLocation={this._onDidChangeUserLocation.bind(this) }
            />
        );
    }

    zoomToLocs(locs,isRegionChange) {
        if (!Array.isArray(locs) && Object.prototype.toString.call(locs) === '[object Object]') {
            locs = [locs];
        }
        if (!Array.isArray(locs)) {
            return;
        }

        UIManager.dispatchViewManagerCommand(
            this.getMapViewHandle(),
            UIManager.RCTBaiduMapView.Commands.zoomToLocs,
            [locs,isRegionChange]
        );
    }

    /**
     * 根据参数开启GPS定位
     */
    startUserLocation(options: Object) {
        UIManager.dispatchViewManagerCommand(
            this.getMapViewHandle(),
            UIManager.RCTBaiduMapView.Commands.startUserLocation,
            [options]
        );
    }

    /**
     * 停止定位
     */
    stopUserLocation() {
        UIManager.dispatchViewManagerCommand(
            this.getMapViewHandle(),
            UIManager.RCTBaiduMapView.Commands.stopUserLocation,[]);
    }

    addPointAnnotation(pointInfo: Object) {
        let { annotations } = this.state;
        annotations = annotations || [];
        annotations.push(pointInfo);
        this.setState({annotations});
        UIManager.dispatchViewManagerCommand(
            this.getMapViewHandle(),
            UIManager.RCTBaiduMapView.Commands.addPointAnnotation,
            [pointInfo]
        );
    }

    updatePointAnnotation(pointInfo: Object) {
        UIManager.dispatchViewManagerCommand(
            this.getMapViewHandle(),
            UIManager.RCTBaiduMapView.Commands.updatePointAnnotation,
            [pointInfo]
        );
    }

    /**
     * 修改百度地图的状态
     */
    chanageMapStates(mapState: baiduMapState) {
        UIManager.dispatchViewManagerCommand(
            this.getMapViewHandle(),
            UIManager.RCTBaiduMapView.Commands.chanageMapStates,
            [mapState]
        );
    }

    getMapViewHandle() {
        return ReactNative.findNodeHandle(this.refs["baiduMap"]);
    }

    _onDidChangeUserLocation(event: Event) {
        if (typeof this.props['onDidChangeUserLocation'] === 'function') {
            this.props['onDidChangeUserLocation'](event.nativeEvent);
        }
    }

    componentWillUnmount() {//组件移除后，停止定位服务
        if (Platform.OS === 'android') {
            this.stopUserLocation();
        }
    }
}

const styles = StyleSheet.create({
    annotationView: {
        position: 'absolute',
        backgroundColor: 'transparent',
    },
    calloutView: {
        position: 'absolute',
        backgroundColor: 'white',
    },
});

/**
 * Standard iOS MapView pin color constants, to be used with the
 * `annotation.tintColor` property. On iOS 8 and earlier these are the
 * only supported values when using regular pins. On iOS 9 and later
 * you are not obliged to use these, but they are useful for matching
 * the standard iOS look and feel.

let PinColors = RCTBaiduMapConstants && RCTBaiduMapConstants.PinColors;
BaiduMapView.PinColors = PinColors && {
    RED: PinColors.RED,
    GREEN: PinColors.GREEN,
    PURPLE: PinColors.PURPLE,
};
*/

const RCTBaiduMap = requireNativeComponent('RCTBaiduMapView', YuanXinMapView, {
    nativeOnly: {
        onAnnotationDragStateChange: true,
        onAnnotationFocus: true,
        onAnnotationBlur: true,
        onChange: true,
        onPress: true,
        showsZoomControl: true,
        draggable:true
    }
});
